package com.flyemu.share.service;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.flyemu.share.api.Fenxi;
import com.flyemu.share.api.FenxiLogin;
import com.flyemu.share.api.OpenFenxi;
import com.flyemu.share.common.Constants;
import com.flyemu.share.dto.RelationCwDto;
import com.flyemu.share.entity.*;
import com.flyemu.share.exception.ServiceException;
import com.flyemu.share.repository.RelationAccountRepository;
import com.flyemu.share.repository.RelationCwRepository;
import com.flyemu.share.repository.RelationSubjectRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class RelationCwService extends AbsService {
    private final Fenxi fenxi;
    private final FenxiLogin fenxiLogin;
    private final RelationCwRepository relationCwRepository;
    private final RelationAccountRepository relationAccountRepository;
    private final RelationSubjectRepository subjectRepository;
    private static final QRelationCw qRelationCw = QRelationCw.relationCw;
    private static final QRelationAccount qRelationAccount = QRelationAccount.relationAccount;
    private static final QRelationSubject qRelationSubject = QRelationSubject.relationSubject;
    private static final QOrganization qOrganization = QOrganization.organization;
    private static final QAdmin qAdmin = QAdmin.admin;


    @Transactional
    public Object loadAccountSets(Long relationCwId, Long accountSetsId, Long merchantId, Long organizationId) {
        RelationAccount relationAccount = bqf.selectFrom(qRelationAccount)
                .where(qRelationAccount.relationCwId.eq(relationCwId).and(qRelationAccount.merchantId.eq(merchantId)).and(qRelationAccount.organizationId.eq(organizationId))).fetchFirst();
        if (relationAccount == null || StrUtil.isEmpty(relationAccount.getPassword()) && StrUtil.isEmpty(relationAccount.getMobile()) && StrUtil.isEmpty(relationAccount.getUrl())) {
            return relationAccount;
        } else {
            //不为空直接调用接口
            if (StrUtil.isNotEmpty(relationAccount.getCookie())) {
                try {
                    JSONArray array = fenxi.loadAccountSets(relationAccount, accountSetsId);
                    List<Dict> dicts = new ArrayList<>();
                    for (int i = 0; i < array.size(); i++) {
                        JSONObject object = array.getJSONObject(i);
                        Dict dict = new Dict().set("accountSetsId", object.getString("id"))
                                .set("companyName", object.getString("companyName"));
                        dicts.add(dict);
                    }
                    return dicts;
                } catch (Exception e) {
                    throw new ServiceException("连接财务系统失败！");
                }
            } else { //为空先登录获取cookie
                String cookie = fenxiLogin.getCookie(relationAccount);
                jqf.update(qRelationAccount)
                        .set(qRelationAccount.cookie, cookie)
                        .where(qRelationAccount.id.eq(relationAccount.getId())).execute();
                relationAccount.setCookie(cookie);

                try {
                    JSONArray array = fenxi.loadAccountSets(relationAccount, accountSetsId);

                    List<Dict> dicts = new ArrayList<>();
                    for (int i = 0; i < array.size(); i++) {
                        JSONObject object = array.getJSONObject(i);
                        Dict dict = new Dict().set("accountSetsId", object.getString("id"))
                                .set("companyName", object.getString("companyName"));
                        dicts.add(dict);
                    }
                    return dicts;
                } catch (Exception e) {
                    throw new ServiceException("连接财务系统失败！");
                }
            }
        }
    }

    public List<RelationCwDto> load(Long merchantId, Long organizationId) {
        List<RelationCwDto> dtos = new ArrayList<>();
        bqf.selectFrom(qOrganization)
                .select(qRelationCw, qOrganization.name, qOrganization.code, qAdmin.name, qRelationAccount.id, qRelationAccount.mobile)
                .leftJoin(qRelationCw).on(qOrganization.id.eq(qRelationCw.organizationId).and(qRelationCw.merchantId.eq(merchantId)))
                .leftJoin(qAdmin).on(qRelationCw.adminId.eq(qAdmin.id))
                .leftJoin(qRelationAccount).on(qRelationAccount.relationCwId.eq(qRelationCw.id))
                .where(qOrganization.id.eq(organizationId).and(qOrganization.merchantId.eq(merchantId))).fetch().forEach(tuple -> {
                    RelationCwDto dto = new RelationCwDto();
                    dto.setIsRelation(false);
                    if (tuple.get(qRelationCw) != null) {
                        dto = BeanUtil.toBean(tuple.get(qRelationCw), RelationCwDto.class);
                        dto.setAdminName(tuple.get(qAdmin.name));
                    }
                    dto.setRelationAccountId(tuple.get(qRelationAccount.id));
                    dto.setRelationAccountMobile(tuple.get(qRelationAccount.mobile));
                    dto.setOrganizationName(tuple.get(qOrganization.name));
                    dto.setOrganizationCode(tuple.get(qOrganization.code));
                    dtos.add(dto);
                });
        return dtos;
    }

    /**
     * 保存/更新
     *
     * @param relationCw
     * @return
     */
    @Transactional
    public Long save(RelationCw relationCw) {
        RelationAccount relationAccount = bqf.selectFrom(qRelationAccount).where(qRelationAccount.relationCwId.eq(relationCw.getId()).and(qRelationAccount.merchantId.eq(relationCw.getMerchantId())).and(qRelationAccount.organizationId.eq(relationCw.getOrganizationId()))).fetchFirst();
        relationCw.setUpdateDate(LocalDateTime.now());
        if (relationCw.getIsRelation()) {
            Assert.isTrue(relationCw.getAccountSetsId() != null && StrUtil.isNotEmpty(relationCw.getCompanyName()), "财务帐套数据为空");
        } else {
            relationCw.setAccountSetsId(null);
            relationCw.setCompanyName(null);
            jqf.delete(qRelationAccount).where(qRelationAccount.relationCwId.eq(relationCw.getId()).and(qRelationAccount.merchantId.eq(relationCw.getMerchantId())).and(qRelationAccount.organizationId.eq(relationCw.getOrganizationId()))).execute();
            jqf.delete(qRelationSubject).where(qRelationSubject.cwRelationId.eq(relationCw.getId()).and(qRelationSubject.organizationId.eq(relationCw.getOrganizationId())).and(qRelationSubject.merchantId.eq(relationCw.getMerchantId()))).execute();
            relationCwRepository.save(relationCw);
            return null;
        }
        Map<String, Dict> subMap = new HashMap<>();
        fenxi.loadSubject(relationAccount, relationCw.getAccountSetsId()).toJavaList(Dict.class).forEach(item -> {
            subMap.put(item.getStr("name"), item);
        });


        jqf.delete(qRelationSubject)
                .where(qRelationSubject.merchantId.eq(relationCw.getMerchantId()).and(qRelationSubject.organizationId.eq(relationCw.getOrganizationId())).and(qRelationSubject.cwRelationId.eq(relationCw.getId()))).execute();

        relationCw = relationCwRepository.save(relationCw);
        lazyDao.batchUpdate("initSubjectRelation", toRelations(relationCw.getMerchantId(), relationCw.getOrganizationId(), relationCw.getId(), relationCw.getAccountSetsId(), subMap));

//        if (relationCw.getId() == null) {
//            relationCw = relationCwRepository.save(relationCw);
//            lazyDao.batchUpdate("initSubjectRelation", toRelations(relationCw.getMerchantId(), relationCw.getOrganizationId(), relationCw.getId(), relationCw.getAccountSetsId(), subMap));
//        } else {
//            RelationCw orgRelationCw = relationCwRepository.getById(relationCw.getId());
//            if (orgRelationCw.getAccountSetsId() != null && !orgRelationCw.getAccountSetsId().equals(relationCw.getAccountSetsId())) {
//                List<RelationSubject> subjects = new ArrayList<>();
//                Long accountSetsId = relationCw.getAccountSetsId();
//                //重新根据名字匹配默认的科目
//                bqf.selectFrom(qRelationSubject)
//                        .where(qRelationSubject.merchantId.eq(relationCw.getMerchantId()).and(qRelationSubject.organizationId.eq(relationCw.getOrganizationId())).and(qRelationSubject.cwRelationId.eq(relationCw.getId())))
//                        .fetch().forEach(tuple -> {
//                            RelationSubject subject = tuple;
//                            Dict dict = subMap.get(tuple.getTitle());
//                            subject.setAccountSetsId(accountSetsId);
//                            if (dict != null) {
//                                subject.setSubjectId(dict.getLong("id"));
//                                subject.setName(dict.getStr("name"));
//                                subject.setCode(dict.getStr("code"));
//                                subject.setType(dict.getStr("type"));
//                            } else {
//                                subject.setSubjectId(null);
//                                subject.setName(null);
//                                subject.setCode(null);
//                                subject.setType(null);
//                            }
//                            subjects.add(subject);
//                        });
//                subjectRepository.saveAll(subjects);
//            }
//            relationCwRepository.save(relationCw);
//        }
        return relationCw.getAccountSetsId();
    }

    private List<RelationSubject> toRelations(Long merchantId, Long organizationId, Long cwRelationId, Long accountSetsId, Map<String, Dict> subMap) {
        List<String> strings = new ArrayList<>(Arrays.asList("应收账款", "应付账款", "库存盘亏", "库存盘盈", "库存商品", "订单收入", "订单成本", "其他收入", "其他成本", "客户", "供应商"));
        RelationSubject relationSubject = new RelationSubject();
        relationSubject.setMerchantId(merchantId);
        relationSubject.setOrganizationId(organizationId);
        relationSubject.setCwRelationId(cwRelationId);
        relationSubject.setAccountSetsId(accountSetsId);
        List<RelationSubject> relations = new ArrayList<>();
        strings.forEach(str -> {
            RelationSubject sRelation = new RelationSubject();
            BeanUtil.copyProperties(relationSubject, sRelation);
            sRelation.setTitle(str);
            Dict dict = subMap.get(str);
            if (dict != null) {
                sRelation.setSubjectId(dict.getLong("id"));
                sRelation.setName(dict.getStr("name"));
                sRelation.setCode(dict.getStr("code"));
                sRelation.setType(dict.getStr("type"));
            }
            relations.add(sRelation);
        });
        return relations;
    }

}
